package Sequence;
use strict;
use warnings;
use diagnostics;
use constant INF => 10_000;
use Sequence::Infinite::Natural;
use Sequence::Infinite::Prime;
use Sequence::Range;
use Sequence::Infinite::Filter;
use Sequence::Infinite::Map;
use Sequence::Infinite::Concatenate;

use Exporter 'import';
our %EXPORT_TAGS = (
  functions => [qw{Range Sum Product Filter Map Concat}],
  sequences => [qw{Naturals Primes}],
  sugar     => [qw{INF take show say}],
);
@{ $EXPORT_TAGS{all} } = map { @{$_} } values %EXPORT_TAGS;
our @EXPORT_OK = @{ $EXPORT_TAGS{all} };

sub Range($)    { new Sequence::Range( @_ ) }
sub Sum         { my $s = 0; $s += $_ for @{ shift() }; $s }
sub Product     { my $p = 1; $p *= $_ for @{ shift() }; $p }
sub Filter(&$)  { new Sequence::Infinite::Filter( @_ ) }
sub Map(&$)     { new Sequence::Infinite::Map( @_ ) }
sub Concat      { new Sequence::Infinite::Concatenate( @_ ) }

sub Naturals    { new Sequence::Infinite::Natural( @_ ) }
sub Primes      { new Sequence::Infinite::Prime( @_ ) }

sub say { print @_, qq{\n} }
sub show {
  @_ = @{ $_[0] } if( ref( $_[0] ) eq q{ARRAY} );
  '[' . join( q{,}, @_ ) . ']'
}

sub take { my( $count, $what ) = @_;
  return undef unless ref $what;
  
  if( ref($what) eq q{ARRAY} ) {
    [@{$what}[0..$count-1]];
  } elsif( $what->isa('Sequence::Infinite') ) {
    my @xs;
    push( @xs, $what->increment ) for 1..$count;
    [@xs];
  }
}

1;
